home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 029a / new1091.zip / NEW.ASM next >
Assembly Source File  |  1991-10-15  |  43KB  |  1,613 lines

  1.     PAGE    ,132
  2.     TITLE    NEW - Show New Files In Last Specified Days
  3.     SUBTTL    Display new files
  4.  
  5. ;    SET TABS TO 8
  6. ;                                         ;
  7. ;****************************************************************************;
  8. ;                                         ;
  9. ;        Copyright (c) John Pulliam  1989 - 1991  Version 10/15/91         ;
  10. ;                                         ;
  11. ;           For Columbia Data Product Computers and Compatibles         ;
  12. ;                                         ;
  13. ;****************************************************************************;
  14. ;                                         ;
  15. ;    This program displays a list of the files in the specified directory
  16. ;    that were created since midnight of the current day, or optionally
  17. ;    since midnight of any earlier day.
  18. ;
  19. ;    All files with attributes of Hidden, System, Read-Only, Archive,
  20. ;    Volume Label and Directory are displayed along with normal files.
  21. ;
  22. ;    This program may only be used with DOS 2.0 or higher.
  23. ;
  24. ;    This program is released to the Public Domain for non-commercial use
  25. ;    and may be used for commercial use with permission of the author.
  26. ;
  27. ;    The only allowable input commands are:
  28. ;       "NEW"
  29. ;
  30. ;       "NEW/x d:"
  31. ;
  32. ;       "NEW/x d:file.ext", where
  33. ;
  34. ;       "NEW/x d:\dir"
  35. ;
  36. ;       "NEW/x d:\dir\file.ext", where
  37. ;
  38. ;         "x"    is the number of days prior to the current day that files
  39. ;            should be searched for.  The default is 0, the current day.
  40. ;         "d"    is the disk drive that the 'new' files will be displayed
  41. ;            from.
  42. ;         "file" is the name of the file to search for.
  43. ;                   Wild card symbols of * or ? may be used.
  44. ;         "ext"  is the extension of the file name to search for.
  45. ;                   Wild card symbols of * or ? may be used.
  46. ;         "dir" is the directory on drive "d" that the 'new' files will
  47. ;           be displayed from.
  48. ;           The directory can not be entered without the drive.
  49. ;
  50. ;
  51. ;    An ERRORLEVEL of 0  is returned if NO error occurs.
  52. ;    An ERRORLEVEL of 1+ is returned if an error occurs.
  53. ;
  54. ;
  55. ;       Version 10/15/91 added code to display an extension of a
  56. ;    sub-directory name.
  57. ;
  58. ;       Version 6/03/91 corrected a minor bug in some error messages.
  59. ;
  60. ;       Version 2/12/91 of NEW was changed to allow a "file.ext" to be
  61. ;       added in the command line and also display volume labels.
  62. ;
  63. ;    This program is made available for use with no liability assumed by
  64. ;    the author.
  65. ;
  66. ;****************************************************************************;
  67.  
  68. CSEG    SEGMENT PARA PUBLIC
  69.     ASSUME    CS:CSEG,DS:CSEG,ES:CSEG
  70.  
  71.     ORG    100H
  72.  
  73. ;  Select which type of output display format is desired
  74.  
  75. DTYPE    EQU    1        ; 1 = Use the dd-Mon-yy display for the dates
  76.                 ;     ie: 24-Oct-89 for October 24, 1989
  77.  
  78. ;DTYPE    EQU    0        ; 0 = Use the mm-dd-yy    display for the dates
  79.                 ;     ie: 10-24-89 for October 24, 1989
  80.  
  81.  
  82. ;  Define Some Constants
  83.  
  84. CR    EQU    13        ; Carriage Return Code
  85. LF    EQU    10        ; Line Feed Code
  86. MAXLEN    EQU    65        ; Max length for any d:\dir\file spec
  87. CMDLINE EQU    80H        ; Start of command line arguments
  88. FIRST    EQU    4EH        ; Find name of first disk file
  89. NEXT    EQU    4FH        ; Find name of the next disk file
  90.  
  91. ;  File attributes used
  92.  
  93. RO    EQU    01H        ; Read Only attribute bit
  94. HDN    EQU    02H        ; Hidden    attribute bit
  95. SYS    EQU    04H        ; System    attribute bit
  96. VOL    EQU    08H        ; Vol Label attribute bit
  97. DIR    EQU    10H        ; Directory attribute bit
  98. ARC    EQU    20H        ; Archive   attribute bit
  99.  
  100.  
  101. ;  Beginning Of Executable Code
  102.  
  103. NEW:    MOV    DX,OFFSET SMSG1 ; Display initial message
  104.     MOV    AH,9
  105.     INT    21H
  106.  
  107. ;  Make sure that this is DOS 2.0 or higher
  108.  
  109.     CALL    CHKDOS        ; Check DOS version
  110.     CMP    AL,2        ; Want version 2.0 or higher
  111.     JGE    NEW2        ;   so branch if okay
  112.  
  113. ;  Tell User he needs a later version of DOS and quit
  114.  
  115.     MOV    AH,9        ; Otherwise tell user and quit
  116.     MOV    DX,OFFSET ERMSG1
  117.     INT    21H
  118.     INC    BYTE PTR ERRFLG
  119. NEW1:    JMP    FINIS        ; Quit if less than DOS 2.0
  120.  
  121.  
  122. ;  Get the System Date from DOS
  123.  
  124. NEW2:    MOV    DI,OFFSET SYSDATE
  125.     CALL    GET_SYSDATE
  126.  
  127. ;  Convert it to 1 hex word containing number of days since 1-Jan-1980
  128.  
  129.     MOV    SI,OFFSET SYSDATE
  130.     MOV    DI,OFFSET SYSDAYS
  131.     CALL    HDATE
  132.  
  133.  
  134. ;  Get the command line arguments if any
  135.  
  136.     CALL    GET_ARGS    ; This stores the specified drive too
  137.     JC    NEW1        ; Quit if an error
  138.  
  139.     CMP    BYTE PTR DRIVE,' '
  140.     JNE    NEW3        ; Skip if drive was in arguments
  141.  
  142.  
  143. ;  Get the default drive & directory & put it in the message
  144.  
  145.     MOV    AH,19H
  146.     MOV    DL,0
  147.     INT    21H        ; Get the default drive
  148.     ADD    AL,'A'        ; Convert number to letter
  149.     MOV    DRIVE,AL
  150.  
  151. NEW3:    CMP    BYTE PTR DIREC,0
  152.     JNZ    NEW4        ; Skip if a directory was in the arguments
  153.  
  154.     MOV    DL,AL
  155.     SUB    DL,40H        ; Drive code (1 = A, etc.)
  156.     MOV    AH,47H
  157.     MOV    SI,OFFSET DIREC
  158.     INT    21H        ; Get the default directory
  159.  
  160. ;  Put the drive, directory  & filespec in FULLNAM too
  161.  
  162. NEW4:    MOV    SI,OFFSET DRIVE
  163.     MOV    DI,OFFSET FULLNAM
  164.     MOV    CX,MAXLEN+3
  165.  
  166. NEW5:    LODSB
  167.     STOSB
  168.     AND    AL,AL
  169.     LOOPNZ    NEW5
  170.     DEC    DI
  171.  
  172. ;  Here FULLNAM will ALWAYS contain at least the 'drive:\directory'
  173.  
  174.     CMP    BYTE PTR [DI-1],'\'
  175.     JE    NEW6        ; Add '*.*' after dir\
  176.     CMP    BYTE PTR HASDOT,0
  177.     JNZ    NEW8        ; Add nothing after file.ext
  178.                 ;   or else add '\*.*' after dir
  179.     MOV    AL,'\'        ; Add '\*.*' after filespec
  180.     STOSB
  181.  
  182. ;  Add '*.*' after filespec
  183.  
  184. NEW6:    MOV    BYTE PTR [DI],'*'
  185.     MOV    BYTE PTR [DI+1],'.'
  186.     MOV    BYTE PTR [DI+2],'*'
  187.  
  188.  
  189. ;  Set the DTA to our filespec buffer
  190.  
  191. NEW8:    MOV    AH,1AH
  192.     MOV    DX,OFFSET FSPEC
  193.     INT    21H
  194.  
  195.  
  196. ;  Display the header info
  197.  
  198.     MOV    CX,80
  199.     MOV    SI,OFFSET SMSG2
  200. NEW10:    LODSB
  201.     CMP    AL,0        ; Don't display or count zeros
  202.     JZ    NEW10
  203.     CMP    AL,'$'        ; Quit when '$' is found
  204.     JE    NEW12
  205.     MOV    DL,AL
  206.     MOV    AH,2
  207.     INT    21H
  208.     LOOP    NEW10
  209.  
  210.  
  211. ;  Our compare date is set to System date minus number of days in command line
  212. ;  Since the file time is not looked at, any file of the proper day will be
  213. ;  a "match".
  214.  
  215.  
  216. ;  Loop here "finding" every file, checking the date/time and display
  217. ;  the file name if it was created after our COMDAYS.
  218.  
  219. NEW12:    MOV    CX,12        ; Clear the file name buffer for grins
  220.     MOV    DI,OFFSET FILENAM
  221.     MOV    AL,0
  222.     REP    STOSB
  223.  
  224. ;  DOS stores the file name in FSPEC+30 (FILENAM label)
  225.  
  226.     CALL    FINDFILE    ; Get the first or next file
  227.     JNC    NEW13        ; Skip if file found okay
  228.     CMP    AX,12H        ; See if no more files
  229.     JE    QUIT        ; Exit if no more files
  230.     JMP    FINIS        ; Quit if non-existant directory
  231.  
  232.  
  233. ;  Get the file date/time from the FCB returned by DOS
  234.  
  235. NEW13:    MOV    DI,OFFSET FILDATE
  236.     CALL    GET_FILDATE
  237.  
  238. ;  Convert the file date to the number of days since 1-Jan-1980
  239.  
  240.     MOV    SI,OFFSET FILDATE
  241.     MOV    DI,OFFSET FILDAYS
  242.     CALL    HDATE
  243.  
  244. ;  Compare the file date/time with Comdays date/time.
  245.  
  246.     MOV    AX,FILDAYS    ; File days since 1/1/80
  247.     CMP    AX,COMDAYS    ; Compare days
  248.     JL    NEW16        ; Skip if file days is older
  249.  
  250.  
  251. ;  Display the file information if we have a match
  252.  
  253. NEW14:    CALL    DISP        ; Display the file name
  254.     INC    WORD PTR TOTFILE; Increment the total number of files
  255.  
  256.  
  257. ;  Loop for the next file
  258.  
  259. NEW16:    JMP    NEW12
  260.  
  261.  
  262. ;  Exit back to DOS
  263.  
  264. QUIT:    MOV    SI,OFFSET TOTFILE
  265.     MOV    DI,OFFSET TOTF
  266.     CALL    HEX_DEC8    ; Get total files in decimal
  267.     JC    FINIS
  268.  
  269.     MOV    SI,OFFSET TOTSIZE
  270.     MOV    DI,OFFSET TOTS
  271.     CALL    HEX_DEC8    ; Get total bytes in decimal
  272.     JC    FINIS
  273.  
  274.     CMP    WORD PTR TOTFILE,1
  275.     JNE    Q1
  276.  
  277.     MOV    BYTE PTR TOTFS,' '
  278. Q1:    MOV    SI,OFFSET SMSG3 ; Display the totals
  279.     MOV    CX,80
  280. Q2:    LODSB
  281.     CMP    AL,0        ; Ignore null codes
  282.     JZ    Q2
  283.     CMP    AL,'$'
  284.     JE    Q4        ; Finished if '$'
  285.     MOV    DL,AL
  286.     MOV    AH,2
  287.     INT    21H
  288.     LOOP    Q2
  289.  
  290. ;  Get and display the free bytes on the drive
  291.  
  292. Q4:    MOV    DL,DRIVE
  293.     SUB    DL,40H        ; 1 = drive A, etc.
  294.     MOV    SI,OFFSET FREESIZ
  295.     MOV    DI,OFFSET SIZLEFT
  296.     CALL    FREE_SPACE    ; Get the free space
  297.  
  298.     MOV    SI,OFFSET SMSG4    ; Display the free bytes on the drive
  299.     MOV    CX,80
  300. Q5:    LODSB
  301.     CMP    AL,0        ; Ignore null codes
  302.     JZ    Q5
  303.     CMP    AL,'$'
  304.     JE    FINIS        ; Finished if '$'
  305.     MOV    DL,AL
  306.     MOV    AH,2
  307.     INT    21H
  308.     LOOP    Q5
  309.  
  310. FINIS:    MOV    AH,4CH
  311.     MOV    AL,ERRFLG    ; Use ERRFLG for a return code
  312.     INT    21H        ; Return to DOS When Finished
  313.  
  314.     SUBTTL    Miscellaneous Callable Routines
  315.     PAGE    +
  316.  
  317. ;
  318. ;****************************************************************************;
  319. ;
  320. ;  DISP - Display The File Name And Information
  321. ;
  322. ;  This routine assembles the information for each line to be displayed
  323. ;  then writes it to the CRT.
  324. ;
  325. ;  Entry:  None
  326. ;
  327. ;  Exit:   None
  328. ;
  329. ;  Alters: All registers are altered
  330. ;
  331. ;****************************************************************************;
  332. ;
  333.  
  334. DISP:    MOV    BYTE PTR DIRFLG,0
  335.  
  336. ;  Need special handling for directory names
  337.  
  338.     MOV    DL,FSPEC+21    ; Get the file attributes
  339.     CMP    DL,DIR        ; See if it a directory or subdirectory
  340.     JNE    DISP6        ; Branch to display normal file name if not
  341.  
  342. ;  Have directory name
  343.  
  344. ;  Need special handling for "." & ".." directory names
  345.  
  346.     MOV    SI,OFFSET FILENAM
  347.     MOV    DX,OFFSET DOT
  348.     CMP    BYTE PTR [SI],'.'
  349.     JNE    DISP1        ; Skip if not '.'
  350.  
  351.     CMP    BYTE PTR [SI+1],0
  352.     JE    DISP4        ; Skip if not '.',0
  353.  
  354.     MOV    DX,OFFSET DOTDOT; Check for '..',0
  355.     CMP    WORD PTR [SI+1],002EH
  356.     JE    DISP4        ; Branch to display ".." directory name
  357.  
  358. ;  Have a subdirectory name so display it
  359.  
  360. DISP1:    MOV    SI,OFFSET FILENAM
  361.     MOV    CX,8
  362. DISP2:    LODSB
  363.     AND    AL,AL
  364.     JNZ    DISP3
  365.     MOV    AL,' '
  366. DISP3:    MOV    DL,AL
  367.     MOV    AH,2
  368.     INT    21H
  369.     LOOP    DISP2
  370.  
  371. ;  Add a space and the sub-directory extension
  372.  
  373.     MOV    AH,2        ; Add a space before the extension
  374.     MOV    DL,' '
  375.     INT    21H
  376.  
  377.     CALL    DISPEXT        ; Write the extension
  378.     JMP    SHORT DISP5
  379.  
  380. ;  Have a "." or ".." directory name
  381.  
  382. DISP4:    MOV    AH,9
  383.     INT    21H        ; Display '.' or '..' name
  384.  
  385. DISP5:    MOV    DX,OFFSET DIRNAME
  386.     MOV    AH,9        ; Display the '<DIR>'
  387.     INT    21H
  388.     MOV    DI,OFFSET FSIZE+2
  389.     MOV    CX,8
  390.     MOV    AL,' '
  391.     REP    STOSB        ; Blank fill the file size
  392.     MOV    BYTE PTR DIRFLG, 1
  393.     JMP    SHORT DISP17    ; Branch to continue with the file attributes
  394.  
  395.  
  396. ;  Display the file name
  397.  
  398. DISP6:    MOV    CX,8
  399.     MOV    SI,OFFSET FILENAM
  400.  
  401. DISP8:    LODSB
  402.     CMP    AL,0        ; Quit when 0 is found
  403.     JZ    DISP9
  404.     CMP    AL,'.'        ; Quit when '.' is found
  405.     JNE    DISP10
  406.  
  407. DISP9:    MOV    DL,' '        ; Fill in with spaces
  408.     MOV    AH,2
  409.     INT    21H
  410.     LOOP    DISP9
  411.     JMP    SHORT DISP13    ; Branch to display the extension
  412.  
  413. DISP10:    MOV    DL,AL
  414.     MOV    AH,2
  415.     INT    21H
  416.     LOOP    DISP8
  417.  
  418.     TEST    BYTE PTR FSPEC+21,VOL    ; Check for Vol Label attribute
  419.     JZ    DISP13        ; Skip if not volume label
  420.     MOV    CX,4        ; Display up to 4 more symbols of vol label
  421.     JMP    SHORT DISP14    ; Branch to display remainder of vol label
  422.  
  423. ;  Add a space before the extension and write the extension
  424.  
  425. DISP13:    MOV    AH,2        ; Add a space before the extension
  426.     MOV    DL,' '
  427.     INT    21H
  428.  
  429. DISP14:    CALL    DISPEXT        ; Write the extension
  430.  
  431. ;  Get the file size & update the total size
  432.  
  433.     MOV    SI,OFFSET FSPEC+26
  434.     MOV    DI,OFFSET FSIZE+2
  435.     MOV    AX,[SI]     ; Keep running total of bytes
  436.     ADD    WORD PTR TOTSIZE,AX
  437.     MOV    AX,[SI+2]    ; Upper word of total bytes
  438.     ADC    WORD PTR TOTSIZE+2,AX
  439.     CALL    HEX_DEC8    ; Convert the file size to decimal
  440.  
  441. ;  Fill in the file attributes in the message
  442.  
  443. ; Attribute
  444.  
  445. ; none =  0
  446. ; RO   =  1
  447. ; HDN  =  2
  448. ; SYS  =  4
  449. ; VOL  =  8
  450. ; DIR  = 10
  451. ; ARC  = 20
  452.  
  453. DISP17:    MOV    DI,OFFSET ATTS    ; Point to the message buffer
  454.     MOV    CX,24        ; Length of the buffer
  455.     MOV    AL,' '
  456.     REP    STOSB        ; Clear the previous file attributes
  457.  
  458.     MOV    DL,FSPEC+21    ; Get the current file attributes
  459.     MOV    SI,OFFSET ATT_TXT; Text string pointer
  460.     MOV    DI,OFFSET ATTS    ; Message buffer pointer
  461.     MOV    DH,1        ; Attribute mask
  462.  
  463. DISP18:    TEST    DL,DH        ; See if this attribute is set
  464.     JZ    DISP19        ; Skip if it is not set
  465.     MOV    AX,WORD PTR [SI+0]
  466.     STOSW            ; Store the first two symbols
  467.     MOV    AX,WORD PTR [SI+2]
  468.     STOSW            ; Store the last two symbols
  469. DISP19:    ADD    SI,4        ; Move text string pointer
  470.     SHL    DH,1        ; Move attribute mask
  471.     CMP    DH,20H        ; See if this is the last one
  472.     JLE    DISP18        ; Repeat until finished
  473.  
  474.  
  475. ;  Display the file size, date, time & attributes
  476.  
  477.     MOV    SI,OFFSET FSIZE ; Display the file size, date & time
  478.     MOV    CX,80
  479.     CMP    BYTE PTR DIRFLG,0
  480.     JZ    DISP22        ; Skip if not directory or subdirectory
  481.     ADD    SI,6
  482.     SUB    CX,6
  483.  
  484. DISP22:    LODSB
  485.     CMP    AL,0        ; Replace NULL codes with space codes
  486.     JNZ    DISP23
  487.     MOV    AL,' '
  488. DISP23: CMP    AL,'$'        ; Finished if it is a '$'
  489.     JE    DISP24
  490.     MOV    DL,AL
  491.     MOV    AH,2
  492.     INT    21H
  493.     LOOP    DISP22        ; Repeat until finished
  494.  
  495. DISP24: RET
  496.  
  497. ;
  498. ;****************************************************************************;
  499. ;
  500. ;  DISPEXT - Display The File Name Extension
  501. ;
  502. ;  This routine assembles and displays the file name extension.
  503. ;
  504. ;  Entry:  None
  505. ;
  506. ;  Exit:   None
  507. ;
  508. ;  Alters: All registers are altered
  509. ;
  510. ;****************************************************************************;
  511. ;
  512.  
  513. DISPEXT:
  514.     MOV    AH,2        ; Add a space before the extension
  515.     MOV    DL,' '
  516.     INT    21H
  517.     MOV    CX,3        ; Display up to 3 symbols of extension
  518.  
  519. ;  Display the sub-directory extension
  520.  
  521. DISPX1:    LODSB
  522.     CMP    AL,'.'
  523.     JE    DISPX1        ; Ignore the period if still here
  524.     CMP    AL,0        ; Quit when 0 is found
  525.     JNZ    DISPX2
  526.     MOV    AL,' '        ; Write a space instead of a zero
  527.  
  528. DISPX2:    MOV    DL,AL        ; Write the next symbol
  529.     MOV    AH,2
  530.     INT    21H
  531.     LOOP    DISPX1
  532.     RET
  533.  
  534. ;
  535. ;****************************************************************************;
  536. ;
  537. ;  Check DOS version and return it in AL
  538. ;
  539. ;  This routine fetches the version of DOS that is currently being used.
  540. ;
  541. ;  Entry:  None
  542. ;
  543. ;  Exit:   AL contains the version, 2, 3 etc.
  544. ;
  545. ;  Alters: All registers are altered
  546. ;
  547. ;****************************************************************************;
  548. ;
  549.  
  550. CHKDOS: MOV    AH,30H        ; Fetch DOS version
  551.     INT    21H        ; Call DOS
  552.     AND    AL,07H        ; Discard unused upper bits
  553.     RET
  554.  
  555. ;
  556. ;****************************************************************************;
  557. ;
  558. ;  GET_ARGS - Get Command Line Arguments
  559. ;
  560. ;  Entry:  None
  561. ;
  562. ;  Exit:   The ASCII number is in NDAYS.
  563. ;       The drive is in DRIVE.
  564. ;       The directory is in DIREC.
  565. ;
  566. ;       The Carry flag is set if there is an error in the arguments.
  567. ;
  568. ;  Alters: All registers are altered
  569. ;
  570. ;****************************************************************************;
  571. ;
  572.  
  573. GET_ARGS:
  574.     MOV    SI,CMDLINE
  575.     MOV    CH,0
  576.     LODSB
  577.     MOV    CL,AL        ; Length of args in CX
  578.  
  579.     CMP    AL,0
  580.     JZ    GA8        ; Skip to return if no arguments
  581.     CALL    CHKDOT        ; See if arg list contains '.'
  582.     LODSB
  583.     DEC    CX
  584.     JCXZ    GA8        ; Return if no more symbols in argument list
  585.     CMP    AL,'/'
  586.     JNE    GA2        ; Skip if not a slash
  587.  
  588. ;  Pick up the number of days from the cmd line
  589.  
  590.     MOV    BX,0
  591. GA1:    LODSB            ; Get next symbol
  592.     DEC    CX
  593.     CMP    AL,CR
  594.     JE    GA8        ; Branch to return if end of the args
  595.     CMP    AL,' '
  596.     JE    GA2        ; Skip if end of the number
  597.     CMP    AL,'0'
  598.     JL    GA5        ; Skip if < '0'
  599.     CMP    AL,'9'
  600.     JG    GA5        ; Skip if > '9'
  601.     SUB    AL,30H        ; Convert to a hex number
  602.     MOV    NDAYS[BX],AL    ; Store this digit of the number of days
  603.     JCXZ    GA8        ; Return if no more symbols
  604.     INC    BX
  605.     CMP    BX,4        ; Max number of digits
  606.     JL    GA1        ; Loop for next digit if okay yet
  607.     LODSB            ; Pick up the next symbol
  608.     DEC    CX
  609.     CMP    AL,CR
  610.     JE    GA8        ; Branch to return if end of the args
  611.     CMP    AL,' '
  612.     JNE    GA5        ; Branch to report error if not a space
  613.  
  614.  
  615. ;  Skip over any spaces
  616.  
  617. GA2:    CMP    AL,' '
  618.     JNE    GA3        ; Skip if not a space
  619.     JCXZ    GA8        ; Return if no more symbols
  620.  
  621.     MOV    DI,SI
  622.     MOV    AL,' '
  623.     REPE    SCASB
  624.     DEC    DI
  625.     MOV    SI,DI
  626.     LODSB            ; Pick up the next symbol
  627.  
  628.  
  629. ;  Get the disk drive and see if it is valid
  630.  
  631. GA3:    CMP    BYTE PTR [SI],':'
  632.     JNE    GA5        ; Branch if not a valid drive
  633.  
  634.     AND    AL,5FH        ; Convert drive to upper case
  635.     CALL    VAL_DRIVE
  636.     JC    GA6        ; Branch to return if not a valid drive
  637.  
  638.     MOV    DRIVE,AL    ; Store the drive letter
  639.  
  640. ;  Pick up the directory if it is in the cmd line args
  641.  
  642.     INC    SI        ; Point to the '\'
  643.     CMP    BYTE PTR [SI],'\'
  644.     JNE    GA8        ; Finished if no directory
  645.  
  646.     MOV    CX,MAXLEN-2
  647.     INC    SI
  648.     MOV    DI,OFFSET DIREC
  649. GA4:    LODSB            ; Get the directory
  650.     CMP    AL,CR
  651.     JE    GA8
  652.     STOSB            ; Store the directory & filespec
  653.     LOOP    GA4
  654.  
  655.     JMP    SHORT GA8    ; Finished so return
  656.  
  657. ;  Report invalid arguments
  658.  
  659. GA5:    MOV    AH,9
  660.     MOV    DX,OFFSET ERMSG2
  661.     INT    21H
  662.     INC    BYTE PTR ERRFLG
  663.  
  664. GA6:    STC
  665.     RET            ; Return after error
  666.  
  667. ;  Now need to assemble the number of days since 1-Jan-1980
  668.  
  669. GA8:    CALL    GET_DAYS    ; SI points to the next symbol
  670.     RET            ; Return to calling routine
  671.  
  672. ;
  673. ;****************************************************************************;
  674. ;
  675. ;  CHKDOT - Check for a '.' in the argument list
  676. ;
  677. ;  Entry:  CX = Length of argument list to scan
  678. ;          SI = Start of argument list to scan
  679. ;
  680. ;  Exit:   Byte variable HASDOT = 0 if a '/./' is not found in the arg list.
  681. ;          Byte variable HASDOT = 1 if a '/./' is found in the arg list.
  682. ;
  683. ;  Alters: Only the flag register is altered
  684. ;
  685.  
  686. CHKDOT:    PUSH    CX        ; Save registers
  687.     PUSH    DI
  688.     PUSH    AX
  689.     MOV    BYTE PTR HASDOT,0; Initially clear the flag
  690.     MOV    AL,'.'
  691.     MOV    DI,SI
  692.     REPNE    SCASB        ; Scan for '.'
  693.     JNE    CHKDOT1
  694.     MOV    BYTE PTR HASDOT,1; Set flag since '.' was found
  695. CHKDOT1:POP    AX        ; Restore registers
  696.     POP    DI
  697.     POP    CX
  698.     RET
  699. ;
  700. ;****************************************************************************;
  701. ;
  702. ;  GET_DAYS - Convert the command line input in NDAYS from hex bytes to a
  703. ;          hex number of days in HDAYS.
  704. ;
  705. ;  Entry:  None
  706. ;
  707. ;  Exit:   None
  708. ;
  709. ;  Alters: Only the flag register is altered.
  710. ;
  711. ;****************************************************************************;
  712. ;
  713.  
  714. GET_DAYS:
  715.     PUSH    AX        ; Save registers
  716.     PUSH    BX
  717.     PUSH    CX
  718.     PUSH    DI
  719.     PUSH    SI
  720.  
  721. ;  Convert from NDAYS to the one word hex number in HDAYS
  722.  
  723. GD2:    MOV    SI,OFFSET NDAYS
  724.  
  725. ; NDAYS contains four "decimal" numbers - need hex to get COMDAYS
  726.  
  727. ;  Move the 4 decimal digits to TEMP, right shifted
  728.  
  729.     MOV    SI,OFFSET NDAYS
  730.     MOV    AH,4
  731.  
  732. GD3:    CMP    BYTE PTR [SI],' '
  733.     JE    GD5        ; Done if space code in NDAYS
  734.     MOV    DI,OFFSET TEMP    ; Point to temporary buffer
  735.     MOV    CX,3
  736. GD4:    MOV    AL,[DI+1]    ; Left shift the bytes in the buffer
  737.     STOSB
  738.     LOOP    GD4
  739.  
  740.     LODSB            ; Get next digit from NDAYS
  741.     STOSB            ; Store it right shifted in temporary buffer
  742.     DEC    AH
  743.     JNZ    GD3        ; Repeat until space is found in NDAYS
  744.  
  745. ;  Convert 4 decimal digits in TEMP to one hex word in HDAYS
  746.  
  747. GD5:    MOV    SI,OFFSET TEMP    ; Input buffer
  748.     MOV    DI,OFFSET HDAYS ; Output buffer
  749.  
  750.     LODSW            ; Upper 2 decimal digits
  751.     XCHG    AL,AH        ; First digit in AH, second in AL
  752.     AAD            ; Convert two digits to hex in AL
  753.     MOV    CL,100        ; Multiplier
  754.     MUL    CL        ; Multiply by 100 decimal (64 hex)
  755.     MOV    DX,AX        ; Save first two hex digits in DX
  756.  
  757.     LODSW            ; Lower 2 decimal digits
  758.     XCHG    AL,AH        ; Third digit in AH, fourth in AL
  759.     AAD            ; Convert two digits to hex in AL
  760.     ADD    AX,DX        ; Add third & fourth digits to first two
  761.     STOSW            ; Save HDAYS
  762.  
  763. GD6:    MOV    AX,SYSDAYS
  764.     SUB    AX,HDAYS    ; COMDAYS = SYSDAYS - HDAYS
  765.     JG    GD7        ; Branch if > 0   (1 = 1-Jan-80)
  766.     MOV    AX,1        ; Limit COMDAYS to 1-Jan-80
  767. GD7:    MOV    COMDAYS,AX
  768.     CALL    UNHDATE     ; Place COMDAYS in the message
  769.  
  770.     POP    SI        ; Restore registers
  771.     POP    DI
  772.     POP    CX
  773.     POP    BX
  774.     POP    AX
  775.     RET            ; Return to caller
  776.  
  777. ;
  778. ;****************************************************************************;
  779. ;
  780. ;  GET_SYSDATE - GET SYSTEM DATE
  781. ;
  782. ;  This routine fetches the System date & time and stores it in the buffer.
  783. ;
  784. ;  Entry:  DI = Offset of the hex buffer to store it in.
  785. ;
  786. ;       DOS function 2Ah returns the system date as:
  787. ;
  788. ;         CX = Year  (1980 through 2099)
  789. ;         DH = Month (1 through 12)
  790. ;         DL = Day   (1 through 31)
  791. ;
  792. ;
  793. ;       DOS function 2Ch returns the system time as:
  794. ;
  795. ;         CH = Hour    (0 through 23)
  796. ;         CL = Minutes (0 through 59)
  797. ;         DH = Seconds (0 through 59)
  798. ;         DL = Hudredths of seconds (0 through 99)
  799. ;
  800. ;  Exit:   The System date is stored in the buffer in three hex values
  801. ;          as YYMMDD.
  802. ;
  803. ;  Alters: All registers are altered.
  804. ;
  805. ;****************************************************************************;
  806. ;
  807.  
  808. GET_SYSDATE:
  809.     MOV    AH,2AH        ; Get the system date
  810.     INT    21H
  811.  
  812. ;    CX = Year  (1980 through 2099)
  813. ;    DH = Month (1 through 12)
  814. ;    DL = Day   (1 through 31)
  815.     SUB    CX,1980
  816.     MOV    BYTE PTR [DI+0],CL
  817.     MOV    BYTE PTR [DI+1],DH
  818.     MOV    BYTE PTR [DI+2],DL
  819.  
  820.     MOV    AH,2CH        ; Get the system time
  821.     INT    21H
  822.  
  823. ;    CH = Hour    (0 through 23)
  824. ;    CL = Minutes (0 through 59)
  825. ;    DH = Seconds (0 through 59)
  826. ;    DL = Hundredths of seconds (0 through 99)
  827.     MOV    BYTE PTR [DI+3],CH
  828.     MOV    BYTE PTR [DI+4],CL
  829.     MOV    BYTE PTR [DI+5],DH
  830.     MOV    BYTE PTR [DI+6],DL
  831.  
  832.     RET
  833.  
  834. ;                                         ;
  835. ;****************************************************************************;
  836. ;                                         ;
  837. ;    HDATE - Convert A Date To A Hex Number Of Days Since 1-Jan-1980      ;
  838. ;                                         ;
  839. ;    Entry:  SI = Offset of the date to convert.                 ;
  840. ;            The date to convert is in a 3 byte buffer as YYMMDD.         ;
  841. ;            DI = Offset of the buffer to store the result in.         ;
  842. ;                                         ;
  843. ;    Exit:   The date is stored in a one word hex number of the         ;
  844. ;            the number of days since 1-Jan-1980.                 ;
  845. ;            The first byte is the least significant, the second         ;
  846. ;            byte is the most significant.                     ;
  847. ;                                         ;
  848. ;    Alters: All registers are altered.                     ;
  849. ;                                         ;
  850. ;****************************************************************************;
  851.  
  852. ;           1  2  3  4  5  6  7    8  9 10 11 12
  853. DAY    DB    0,31,28,31,30,31,30,31,31,30,31,30,31    ; Days in each month
  854.  
  855. ;  SI    points to the year
  856. ;  SI+1 points to the month
  857. ;  SI+2 points to the day of the month
  858.  
  859. HDATE:    MOV    AL,[SI+2]    ; Get the day of this month
  860.     MOV    AH,0
  861.     MOV    [DI],AX     ; Put it in the buffer
  862.  
  863.     MOV    BYTE PTR DAY+2,28
  864.     MOV    AL,[SI]     ; Get the year
  865.     AND    AL,03H        ; Check for leap year
  866.     JNZ    HD2        ; Skip if not leap year
  867.     INC    BYTE PTR DAY+2    ; Add one to February's days
  868.  
  869. HD2:    MOV    AH,0
  870.     MOV    AL,[SI+1]    ; This month in AX
  871.     DEC    AX        ; Previous month
  872.     JLE    HD6        ; Skip if this month is Jan
  873.  
  874. HD3:    PUSH    AX        ; Save month
  875.     MOV    BX,AX        ; Month for index
  876.     MOV    AL,DAY[BX]    ; Days in the month
  877.     MOV    AH,0
  878.     ADD    WORD PTR [DI],AX; Add the days in this month to total
  879.     POP    AX
  880.     DEC    AX
  881.     JNZ    HD3        ; Repeat for all earlier months
  882.  
  883. ;  Now have the days so far this year - need days of all other years since 80
  884.  
  885. HD6:    MOV    DL,[SI]     ; Get the current year
  886.     DEC    DL        ; Get last year
  887.     JL    HD12        ; Done if this is 1980
  888.  
  889. ;  Loop for each year since 1980
  890.  
  891. HD8:    MOV    AL,DL        ; Get the year
  892.     MOV    CX,365        ; Number of days in a year
  893.     AND    AL,03H        ; Check for leap year
  894.     JNZ    HD9        ; Skip if not leap year
  895.     INC    CX        ; Add one to the year's days
  896.  
  897. ;  Add the number of days in the year to the buffer
  898.  
  899. HD9:    ADD    WORD PTR [DI],CX
  900.     DEC    DL
  901.     JGE    HD8        ; Loop for the next year - Done if negative
  902.  
  903. HD12:    RET
  904.  
  905. ;
  906. ;****************************************************************************;
  907. ;
  908. ;  GET_FILDATE - GET FILE DATE & TIME
  909. ;
  910. ;  This routine gets the file date & time from the FCB after the DOS
  911. ;  Find First or Find Next function has been executed.
  912. ;
  913. ;  Entry:  DI = Offset of the hex buffer to store the date & time in.
  914. ;
  915. ;  Exit:   The file date & time is stored in the hex buffer as:
  916. ;       YYMMDDHHMMSS
  917. ;       The file date & time is stored in the ASCII buffer as:
  918. ;       'MM/DD/YY  HH:MM:SS'
  919. ;
  920. ;  Alters: All registers are altered.
  921. ;
  922. ;  The File Time & Date are obtained from the file FCB as follows:
  923. ;
  924. ;    Time - FCB bytes 22 & 23
  925. ;         Bits 11-15 = Hours   (0 through 23)
  926. ;         Bits 05-10 = Minutes (0 through 59)
  927. ;         Bits 00-04 = Number of 2 second increments (0 through 29)
  928. ;
  929. ;    Date - FCB bytes 24 & 25
  930. ;         Bits 09-15 = Year        (Relative to 1980)
  931. ;         Bits 05-08 = Month     (0 through 12)
  932. ;         Bits 00-04 = Day of month    (0 through 31)
  933. ;
  934. ;****************************************************************************;
  935. ;
  936.  
  937. GET_FILDATE:
  938.  
  939. ;    Date = FCB Bytes 24-25
  940. ;         Bits 09-15 = Year        (Relative to 1980)
  941.     MOV    DI,OFFSET FILDATE
  942.     MOV    AL,FSPEC+25
  943.     MOV    DH,AL
  944.     SHR    AL,1
  945.     AND    AL,7FH
  946.     STOSB            ; Store year in hex buffer
  947.     ADD    AL,80        ; Want two-digit year
  948.     CMP    AL,99        ; Check for greater than 99
  949.     JLE    GF1        ; Skip if not greater than 99
  950.     SUB    AL,100        ; Use "01" for 2001, "11" for 2011, etc.
  951. GF1:    CALL    HEX_DEC2    ; Convert year into two decimal digits
  952.     MOV    SI,OFFSET ADATE
  953. IF DTYPE
  954.     MOV    [SI+7],AX    ; Store year in ASCII string
  955. ELSE
  956.     MOV    [SI+6],AX    ; Store year in ASCII string
  957. ENDIF
  958.  
  959. ;         Bits 05-08 = Month     (0 through 12)
  960.     MOV    AL,FSPEC+24
  961.     MOV    AH,DH
  962.     SHR    AX,1
  963.     AND    AX,0F0H
  964.     SHR    AL,1
  965.     SHR    AL,1
  966.     SHR    AL,1
  967.     SHR    AL,1
  968.     STOSB            ; Store month in hex buffer
  969. IF DTYPE
  970.     DEC    AL        ; Month of 0 - 11 for index
  971.     MOV    AH,AL        ; Put the month in AH
  972.     ADD    AL,AL        ; Multiply month by three for index
  973.     ADD    AL,AH        ; Month times three
  974.     MOV    AH,0
  975.     MOV    CX,3        ; Length of the month text
  976.     PUSH    DI        ; Save these registers
  977.     PUSH    SI
  978.     MOV    DI,SI
  979.     ADD    DI,3        ; Point to the place in the string
  980.     MOV    SI,OFFSET MONTH ; Table of months (Jan, Feb, etc.)
  981.     ADD    SI,AX
  982.     REP    MOVSB        ; Store the month in ASCII string
  983.     POP    SI        ; Now restore these registers
  984.     POP    DI
  985. ELSE
  986.     CALL    HEX_DEC2
  987.     CMP    AL,'0'
  988.     JNE    GF2
  989.     MOV    AL,' '        ; Suppress leading 0 in month
  990. GF2:    MOV    [SI],AX     ; Store the month in ASCII string
  991. ENDIF
  992.  
  993. ;         Bits 00-04 = Day of month    (0 through 31)
  994.     MOV    AL,FSPEC+24
  995.     AND    AL,1FH
  996.     STOSB            ; Store day in hex buffer
  997.     CALL    HEX_DEC2
  998. IF DTYPE
  999.     CMP    AL,'0'        ; Suppress leading zero in day
  1000.     JNE    GF2
  1001.     MOV    AL,' '
  1002.   GF2:    MOV    WORD PTR [SI],AX; Store day in ASCII string
  1003. ELSE
  1004.     MOV    [SI+3],AX    ; Store day in ASCII string
  1005. ENDIF
  1006.  
  1007.  
  1008. ;    Time - FCB Bytes 22-23
  1009. ;         Bits 11-15 = Hours   (0 through 23)
  1010.     MOV    DI,OFFSET FILDATE+3
  1011.     MOV    AL,FSPEC+23
  1012.     AND    AL,0F8H
  1013.     SHR    AL,1
  1014.     SHR    AL,1
  1015.     SHR    AL,1
  1016.     STOSB            ; Store hours in hex buffer
  1017.     CALL    HEX_DEC2    ; Convert to two decimal ASCII symbols
  1018.     MOV    SI,OFFSET ATIME
  1019.     MOV    [SI],AX     ; Store hours in ASCII string
  1020.  
  1021. ;         Bits 05-10 = Minutes (0 through 59)
  1022.     MOV    AL,FSPEC+22
  1023.     MOV    AH,FSPEC+23
  1024.     SHR    AX,1
  1025.     SHR    AX,1
  1026.     SHR    AX,1
  1027.     SHR    AX,1
  1028.     SHR    AX,1
  1029.     AND    AX,3FH
  1030.     STOSB            ; Store minutes in hex buffer
  1031.     CALL    HEX_DEC2
  1032.     MOV    [SI+3],AX    ; Store minutes in ASCII string
  1033.  
  1034. ;         Bits 00-04 = Number of 2 second increments (0 through 29)
  1035.     MOV    AL,FSPEC+22
  1036.     AND    AL,1FH
  1037.     SHL    AL,1        ; Multiply by 2 for actual seconds
  1038.     STOSB            ; Store seconds in hex buffer
  1039.     CALL    HEX_DEC2
  1040.     MOV    [SI+6],AX    ; Store seconds in ASCII string
  1041.  
  1042.     RET
  1043.  
  1044. ;                                         ;
  1045. ;****************************************************************************;
  1046. ;                                         ;
  1047. ;    CONVERT HEX TO DECIMAL ASCII           VERSION 8/25/89         ;
  1048. ;                                         ;
  1049. ;    Convert from 2 hex digits in AL to 2 decimal ASCII symbols in AX.    ;
  1050. ;      (Sometimes called BCD, but other things are also called BCD)         ;
  1051. ;                                         ;
  1052. ;    ENTRY:    AL = The number to convert (00 to 63 hex, 0 to 99 dec).         ;
  1053. ;                                         ;
  1054. ;    EXIT:    AH = Least significant decimal ASCII symbol             ;
  1055. ;        AL = Most  significant decimal ASCII symbol             ;
  1056. ;             as required for writing to the display             ;
  1057. ;        Carry is set if the input number is out of range.         ;
  1058. ;                                         ;
  1059. ;    ALTERS: All registers except CX & DX should be considered altered.   ;
  1060. ;                                         ;
  1061. ;****************************************************************************;
  1062. ;                                         ;
  1063.  
  1064. HEX_DEC2:
  1065.     CMP    AL,99
  1066.     JLE    H_D2        ; Skip if number is okay
  1067.  
  1068.     STC            ; Set carry flag for error
  1069.     JC    H_D3        ; Exit if number is out of range
  1070.  
  1071. H_D2:    AAM            ; Convert two digits to decimal in AX
  1072.     XCHG    AL,AH        ; Lower digit in AH, Upper in AL
  1073.     ADD    AX,3030H    ; Convert to ASCII
  1074.     CLC            ; Clear error flag
  1075.  
  1076. H_D3:    RET            ; Return to calling routine
  1077.  
  1078. ;                                         ;
  1079. ;****************************************************************************;
  1080. ;                                         ;
  1081. ;    Convert Hex To Decimal Ascii           Version 8/31/89         ;
  1082. ;                                         ;
  1083. ;            Copyright (C) John Pulliam  1989             ;
  1084. ;                                         ;
  1085. ;    Convert from 6 hex digits pointed to by SI to 8 decimal ASCII         ;
  1086. ;    symbols in the string pointed to by DI.                  ;
  1087. ;                                         ;
  1088. ;    ENTRY:    SI = Offset of number to convert  (LSW, MSW) where the         ;
  1089. ;             words are arranged LSB, MSB.                 ;
  1090. ;             The maximum input value is 83,886,079 or 4FFFFFF hex.   ;
  1091. ;        DI = Offset of ASCII decimal result.                 ;
  1092. ;                                         ;
  1093. ;    EXIT:  The decimal ASCII symbols are stored in high to low order     ;
  1094. ;           as required for writing to the display                 ;
  1095. ;           The output buffer must be large enough to contain the results.;
  1096. ;                                         ;
  1097. ;           An error is reported to the CRT if the dividend is too large  ;
  1098. ;           and a return is made with the carry flag set.             ;
  1099. ;                                         ;
  1100. ;    ALTERS: All registers should be considered altered.             ;
  1101. ;                                         ;
  1102. ;    NOTE:  The main program must provide the variable, "TEN DW 10".      ;
  1103. ;                                         ;
  1104. ;    Example: Convert 927C0 to 600,000 decimal ASCII.             ;
  1105. ;      600,000 = 9*65536 + 10176                         ;
  1106. ;                                         ;
  1107. ;      HSIZE DW 27C0H, 9                             ;
  1108. ;      DSIZE DB 8 DUP (0)                             ;
  1109. ;                                         ;
  1110. ;      MOV    SI,OFFSET HSIZE                          ;
  1111. ;      MOV    DI,OFFSET DSIZE                          ;
  1112. ;      CALL    HEX_DEC8                             ;
  1113. ;                                         ;
  1114. ;****************************************************************************;
  1115. ;                                         ;
  1116.  
  1117. DFLAG    DB    0        ; Flag for possible overflow
  1118. CRFLG    DB    0        ; Carry flag
  1119. ODD    DB    7 DUP (0)    ; Odd number flag
  1120. DIVOV    DB    CR,LF,7,'Dividend Too Large',CR,LF,'$'
  1121.  
  1122. HEX_DEC8:
  1123.     PUSH    DI        ; Save buffer pointer
  1124.  
  1125.     PUSH    DI        ; Save working register
  1126.     MOV    CX,8
  1127.     MOV    AL,0
  1128.     REP    STOSB        ; Clear the result buffer
  1129.     POP    DI        ; Restore buffer pointer
  1130.  
  1131. ;  Check for valid dividend
  1132.  
  1133.     CMP    WORD PTR [SI+2],1280
  1134.     JL    H_D81        ; Branch if valid
  1135.  
  1136.     MOV    AH,9        ; Report invalid dividend error
  1137.     MOV    DX,OFFSET DIVOV
  1138.     INT    21H
  1139.     STC            ; Set carry flag
  1140.     JMP    H_D89        ; Quit after reporting the error
  1141.  
  1142. ;  Valid dividend so process it
  1143.  
  1144. H_D81:    MOV    DFLAG,0     ; Clear the possible-overflow flag
  1145.     PUSH    DI
  1146.     MOV    CX,7
  1147.     MOV    DI,OFFSET ODD
  1148.     MOV    AL,0
  1149.     REP    STOSB        ; Clear the odd-number flags
  1150.     POP    DI
  1151.     MOV    CX,8        ; Size of the output buffer
  1152.  
  1153.  
  1154. ; Put the hex number to convert in DX,AX & set up buffer pointer
  1155.  
  1156.     LODSW            ; Lower hex word
  1157.     MOV    DX,[SI]     ; Upper hex word
  1158.     ADD    DI,CX
  1159.     DEC    DI        ; Point to right end of the result buffer
  1160.     PUSH    CX        ; Save buffer length and pointer
  1161.     PUSH    DI        ;    for multiply by 2 later
  1162.  
  1163. ;  Prevent Divide Overflow if input is greater than 655359 by dividing
  1164. ;  it by two enough times then multiplying the result by two the same
  1165. ;  number of times.
  1166.  
  1167. H_D82:    CMP    DX,10        ; See if greater than 655359
  1168.     JL    H_D83        ; Skip if not
  1169.  
  1170.     MOV    BH,0
  1171.     MOV    BL,DFLAG    ; Index for ODD flags
  1172.     SHR    AX,1        ; Divide the original number by two
  1173.     ADC    ODD[BX],0    ; Save if number was odd
  1174.     MOV    BX,DX
  1175.     AND    BX,1        ; Get bit 16 of the input
  1176.     ROR    BX,1        ; Rotate into bit 15 position
  1177.     OR    AX,BX        ; Insert bit 15 into AX
  1178.     SHR    DX,1        ; Divide upper word by two
  1179.     INC    DFLAG        ; Set flag so we double the result
  1180.     JMP    H_D82
  1181.  
  1182. ;  Hex to decimal/ascii conversion loop
  1183.  
  1184. ;  Divide the number by ten
  1185.  
  1186. H_D83:    DIV    TEN        ; Divide for the next decimal digit
  1187.     ADD    DL,30H        ; Convert remainder to ASCII symbol (< 10)
  1188.     MOV    [DI],DL     ; Store the ASCII symbol
  1189.     DEC    DI        ; Move buffer pointer left
  1190.     MOV    DX,0        ; Clear upper word
  1191.     LOOP    H_D83        ; Branch to convert all hex digits
  1192.  
  1193.  
  1194. ;  See if we need to double the end result
  1195.  
  1196. H_D84:    POP    DI        ; Get pointer to right end of the buffer
  1197.     POP    CX        ; Get buffer length
  1198.     CMP    DFLAG,0     ; 0 = finished - don't double the result
  1199.     JZ    H_D88        ; Branch when finished
  1200.     MOV    BX,0        ; Initialize ODD index
  1201.  
  1202.  
  1203. ;  Loop here for each time it is necessary to double the end result
  1204.  
  1205. H_D85:    PUSH    CX        ; Save buffer length
  1206.     PUSH    DI        ; Save buffer pointer
  1207.     MOV    CRFLG,0     ; Clear the carry flag
  1208.  
  1209. ;  Multiply the end result by two
  1210.  
  1211. ;  Loop here doing the multiply by 2
  1212.  
  1213. H_D86:    MOV    AL,[DI]     ; Get a symbol
  1214.     SUB    AL,30H        ; Convert to a number
  1215.     SHL    AL,1        ; Multiply the number by two
  1216.     ADD    AL,ODD[BX]    ; Add one if number was odd before divide by 2
  1217.     MOV    ODD[BX],0    ; Clear the ODD flag for this number
  1218.     ADD    AL,CRFLG    ; Add any carry from the previous multiply
  1219.     MOV    CRFLG,0     ; Clear the carry for this symbol
  1220.     CMP    AL,10        ; Check for a carry this time
  1221.     JL    H_D87        ; Branch if no carry this time
  1222.     MOV    CRFLG,1     ; Set the carry flag for next time
  1223.     SUB    AL,10        ; Subtract after carrying
  1224.  
  1225. H_D87:    ADD    AL,30H        ; Convert back to ASCII
  1226.     MOV    [DI],AL     ; Re-store the ASCII symbol
  1227.     DEC    DI        ; Point to the next symbol
  1228.     LOOP    H_D86        ; Repeat for all symbols
  1229.  
  1230.     POP    DI        ; Get pointer to right end of the buffer
  1231.     POP    CX        ; Get buffer length
  1232.     INC    BX
  1233.     DEC    DFLAG        ; Decrement loop counter
  1234.     JG    H_D85        ; Repeat until finished
  1235.  
  1236.  
  1237. ;  Suppress leading zeros of result then return to calling routine
  1238.  
  1239. H_D88:    CLC            ; Clear the error flag
  1240.  
  1241. H_D89:    POP    DI        ; Get start of buffer again
  1242.     PUSHF            ; Save the Carry flag for error flag
  1243.     CALL    SUPPRESS    ; Suppress leading zeros from the result
  1244.     POPF            ; Restore error flag
  1245.     RET            ; Return to calling routine
  1246.  
  1247. ;                                         ;
  1248. ;****************************************************************************;
  1249. ;                                         ;
  1250. ;  This routine suppresses leading zeros in a buffer by replacing them with  ;
  1251. ;  null codes                                     ;
  1252. ;                                         ;
  1253. ;  Entry:  DI = start of the 8 digit buffer.                     ;
  1254. ;                                         ;
  1255. ;  Exit:   The leading zeros in the buffer have been replaced by null codes. ;
  1256. ;                                         ;
  1257. ;  Alters: All registers should be considered altered.                 ;
  1258. ;                                         ;
  1259. ;****************************************************************************;
  1260. ;                                         ;
  1261.  
  1262. SUPPRESS:
  1263.     MOV    CX,7        ; Max number of digits to suppress
  1264.  
  1265. SUP2:    CMP    BYTE PTR [DI],'0'
  1266.     JNE    SUPRET        ; Quit when non-zero is found
  1267.     MOV    BYTE PTR [DI],0 ; Store null code
  1268.     INC    DI        ; Move pointer
  1269.     LOOP    SUP2        ; Repeat until done
  1270.  
  1271. SUPRET: RET
  1272.  
  1273. ;
  1274. ;****************************************************************************;
  1275. ;
  1276. ;  FINDFILE - FIND FIRST OR NEXT FILE
  1277. ;
  1278. ;  Find the first or the next file that matches the filespec.
  1279. ;
  1280. ;  Entry:  The desired filespec must be in FULLNAM in ASCIIZ format.
  1281. ;
  1282. ;  Exit:   Returns the next existing file name in FSPEC+30, 12 bytes long max.
  1283. ;          Carry flag is set if there are no more matching files or if the
  1284. ;       specified directory doesn't exist.
  1285. ;       AX = 12H if there was no matching file.
  1286. ;
  1287. ;  Alters: All registers are altered.
  1288. ;
  1289. ;****************************************************************************;
  1290. ;
  1291.  
  1292. FINDFILE:
  1293.     MOV    DX,OFFSET FULLNAM; Must contain file spec in ASCIIZ format
  1294.     MOV    AH,FUNC     ; Either find "FIRST" or "NEXT" file
  1295.     MOV    BYTE PTR FUNC,NEXT
  1296.  
  1297. ;  Select the desired file attributes
  1298.  
  1299.     MOV    CX,RO + HDN + SYS + VOL + DIR
  1300.     INT    21H        ; Returns file name in FSPEC+30
  1301.     PUSHF            ; Save the carry flag
  1302.     JNC    FF4        ; Branch if okay
  1303.     CMP    AX,12H        ; Check for no more files
  1304.     JE    FF4        ; Branch if no more files
  1305.  
  1306. ;  Report invalid directory
  1307.  
  1308.     PUSH    AX        ; Save the DOS error code
  1309.     MOV    DX,OFFSET ERMSG9; Point to the error message
  1310.     MOV    AH,9
  1311.     INT    21H        ; Display the error message
  1312.      INC    BYTE PTR ERRFLG    ; Increment the error return code
  1313.     POP    AX        ; Retrieve the DOS error code
  1314.  
  1315. FF4:    POPF            ; Retrieve the DOS carry flag
  1316.     RET            ; Return to calling routine
  1317.  
  1318.     PAGE
  1319. ;
  1320. ;****************************************************************************;
  1321. ;
  1322. ;  VAL_DRIVE - Check for a valid disk drive
  1323. ;
  1324. ;  Entry:  AL contains the drive letter.
  1325. ;
  1326. ;  Exit:   Carry is set if the drive is not valid.
  1327. ;
  1328. ;  Alters: Only the Flag register is altered.
  1329. ;
  1330. ;****************************************************************************;
  1331. ;
  1332.  
  1333. ;  Verify that the input file spec of "d:" is a valid drive
  1334.  
  1335. VAL_DRIVE:
  1336.     PUSH    AX        ; Save working registers
  1337.     PUSH    CX
  1338.     PUSH    DX
  1339.     PUSH    DI
  1340.     PUSH    SI
  1341.  
  1342.     AND    AL,0DFH     ; Allow either upper or lower case
  1343.     CMP    AL,'A'        ; Check for legal range of drives
  1344.     JL    VALD2        ; Skip if invalid drive
  1345.  
  1346.     PUSH    AX        ; Save the drive letter
  1347.     SUB    AL,40H        ; Drive A = 1, etc.
  1348.     MOV    DL,AL
  1349.     MOV    AH,36H        ; Verify that it is a valid disk drive
  1350.     INT    21H
  1351.     CMP    AX,-1        ; DOS returns -1 if not a valid drive
  1352.     POP    AX
  1353.     JE    VALD2        ; Branch if invalid drive
  1354.     CLC            ; Clear the carry flag
  1355.     JNC    VALD3        ; Branch to return
  1356.  
  1357. ;  Report invalid drive error
  1358.  
  1359. VALD2:    MOV    DX,OFFSET ERMSG8; Invalid disk drive
  1360.     MOV    AH,9        ; Display WRITE function
  1361.     INT    21H        ; Call DOS
  1362.     MOV    AL,-1        ; Error completion flag
  1363.      INC    BYTE PTR ERRFLG    ; Inc error flag
  1364.     STC            ; Set Carry for error
  1365.  
  1366. VALD3:    POP    SI        ; Restore all of the registers
  1367.     POP    DI
  1368.     POP    DX
  1369.     POP    CX
  1370.     POP    AX
  1371.     RET            ; Return to calling routine
  1372.  
  1373. ;
  1374. ;****************************************************************************;
  1375. ;
  1376. ;  FREE_SPACE - Get the free space on a drive.
  1377. ;
  1378. ;  Entry:  DL = the drive to get the free bytes for.
  1379. ;       SI points to the two word hex result buffer.
  1380. ;       DI points to the eight byte decimal ascii result buffer.
  1381. ;
  1382. ;  Exit:   The result is placed in the external word variable, FREESIZ,
  1383. ;       in two words, LSW, MSW.
  1384. ;       The carry flag is set if an error occurs.
  1385. ;
  1386. ;  Alters: All registers are altered.
  1387. ;
  1388. ;****************************************************************************;
  1389. ;
  1390.  
  1391. FREE_SPACE:
  1392.     MOV    AH,36H        ; Verify that it is a valid disk drive
  1393.     INT    21H
  1394.     CMP    AX,-1        ; DOS returns -1 if not a valid drive
  1395.     JE    FS3        ; Skip if invalid drive
  1396.  
  1397. ;    Multiply (Sectors/Cluster) * (Free Clusters) * (Bytes/Sector)
  1398.  
  1399. FS2:    MUL    BX        ; Sectors per cluster times
  1400.                 ;   number of free clusters times
  1401.     MUL    CX        ;   number of bytes per sector
  1402.     MOV    [SI],AX        ; Least significant word
  1403.     MOV    [SI+2],DX    ; Most  significant word
  1404.     CALL    HEX_DEC8    ; Get total bytes in decimal
  1405.     JNC    FS4        ; Branch to return
  1406.  
  1407. ;  Set error flag if error
  1408.  
  1409. FS3:    INC    BYTE PTR ERRFLG    ; Increment the error flag
  1410.     STC            ; Set carry for error flag
  1411.  
  1412. FS4:    RET            ; Return to calling routine
  1413.  
  1414. ;
  1415. ;****************************************************************************;
  1416. ;
  1417. ;  UNHDATE - Unpack A Hex Date.
  1418. ;
  1419. ;  Entry:  The date to unpack is in COMDAYS.
  1420. ;
  1421. ;  Exit:   The result is placed in the external byte variable, SINCE,
  1422. ;       suitable for writing to the display.
  1423. ;
  1424. ;  Alters: All registers are altered.
  1425. ;
  1426. ;  Note:   The external byte buffer, DAY, must be provided.
  1427. ;
  1428. ;****************************************************************************;
  1429. ;
  1430.  
  1431. UNHDATE:
  1432.     MOV    DAY+2,28    ; Initialize days in February
  1433.     MOV    DX,COMDAYS
  1434.     MOV    BL,0        ; Initial year relative to 1980
  1435.     MOV    CX,365        ; Days in most years
  1436.  
  1437. UNH1:    MOV    DI,365        ; Days in most years
  1438.     MOV    AL,BL        ; The year relative to 1980
  1439.     AND    AL,03H        ; Leap year if zero
  1440.     JNZ    UNH2        ; Skip if not leap year
  1441.     INC    DI        ; Increment for leap year
  1442.     INC    CX        ; Increment total days if leap year
  1443.  
  1444. UNH2:    CMP    CX,DX        ; See if we overshot COMDAYS
  1445.     JGE    UNH4        ; Branch if COMDAYS is this year
  1446.                 ; Equal if Dec 31st.
  1447.     ADD    CX,365        ; Increment total number of days
  1448.                 ; CX increments later if leap year
  1449.     INC    BL        ; Increment to the next year
  1450.     JMP    UNH1        ; Loop until less than a year
  1451.  
  1452. ;  Now BL = year of COMDAYS
  1453.  
  1454. UNH4:    SUB    CX,DI        ; Adjust count of days
  1455.     MOV    AH,0
  1456.     XCHG    AL,BL        ; Year into AX, leap year mask in BL
  1457.     ADD    AX,80        ; Want two-digit year
  1458.     AAM            ; Make year into two decimal digits
  1459.     CMP    AH,9        ; What if it's greater than 99 ?
  1460.     JLE    UNH5
  1461.     SUB    AH,10        ; Use "01" for 2001, "11" for 2011, etc.
  1462. UNH5:    ADD    AX,3030H    ; Make it ASCII
  1463. IF DTYPE
  1464.     MOV    SINCE+7,AH    ; Save year in message
  1465.     MOV    SINCE+8,AL
  1466. ELSE
  1467.     MOV    SINCE+6,AH    ; Save year in message
  1468.     MOV    SINCE+7,AL
  1469. ENDIF
  1470.     AND    BL,03H        ; Zero if leap year
  1471.     SUB    BL,1
  1472.     ADC    DAY+2,0     ; Increment days in Feb if leap year
  1473.  
  1474.     MOV    SI,1        ; Index into days per month
  1475. UNH6:    MOV    AH,0
  1476.     MOV    AL,DAY[SI]    ; AX is the days in this month
  1477.     ADD    CX,AX
  1478.     CMP    CX,DX
  1479.     JGE    UNH8        ; Branch when we've passed it
  1480.     INC    SI
  1481.     JMP    UNH6        ; Loop for another year
  1482.  
  1483. UNH8:    SUB    CX,DX
  1484.     SUB    AX,CX        ; SI = Month, AX = the day of the month
  1485.     MOV    AH,0
  1486.     CALL    HEX_DEC2    ; Make it into ASCII decimal
  1487. IF DTYPE
  1488.     CMP    AL,'0'        ; Suppress leading zero in day
  1489.     JNE    UNH9
  1490.     MOV    AL,' '
  1491. UNH9:    MOV    WORD PTR SINCE,AX; Save day in message
  1492.     DEC    SI        ; Month of 0 - 11 for index
  1493.     MOV    AX,SI        ; Get the month
  1494.     ADD    AX,AX        ; Multiply month by three for index
  1495.     ADD    AX,SI        ; Month times three
  1496.     MOV    CX,3
  1497.     MOV    SI,OFFSET MONTH ; Table of months (Jan, Feb, etc.)
  1498.     ADD    SI,AX
  1499.     MOV    DI,OFFSET SINCE+3
  1500.     REP    MOVSB        ; Store the month
  1501. ELSE
  1502.     MOV    WORD PTR SINCE+3,AX; Save day in message
  1503.     MOV    AX,SI        ; Get the month
  1504.     MOV    AH,0
  1505.     CALL    HEX_DEC2    ; Make it into ASCII decimal
  1506.     CMP    AL,'0'        ; Suppress leading zero in month
  1507.     JNE    UNH9
  1508.     MOV    AL,' '
  1509. UNH9:    MOV    WORD PTR SINCE,AX; Save month in message
  1510. ENDIF
  1511.  
  1512.     RET            ; Return to caller
  1513.  
  1514.  
  1515.     SUBTTL    Messages and Data Storage
  1516.     PAGE    +
  1517.  
  1518.  
  1519. ;  MESSAGES and DATA STORAGE
  1520.  
  1521. ;  Informative messages
  1522.  
  1523. COPY    DB    'Copyright (c) 1989, 1990, 1991 by J.R. Pulliam'
  1524.  
  1525. SMSG1    DB    CR,LF,'NEW - Version 10/15/91 - J. Pulliam'
  1526.     DB    CR,LF,'$'
  1527.  
  1528. ;    THESE ARE AN ORDERED SET - DO NOT RE-ARRANGE THEM
  1529.  
  1530. SMSG2    DB    CR,LF,'Directory of '
  1531. DRIVE    DB    ' :\'
  1532. DIREC    DB    MAXLEN DUP (0)
  1533.     DB    ' since 00:00, '
  1534. IF DTYPE
  1535.   SINCE DB    'DD-Mmm-YY',CR,LF,LF,'$' ; Could include the time?
  1536.   MONTH DB    'JanFebMarAprMayJunJulAugSepOctNovDec'
  1537. ELSE
  1538.   SINCE DB    'MM/DD/YY',CR,LF,LF,'$'  ; Could include the time?
  1539. ENDIF
  1540.  
  1541.  
  1542. ;  File size, date & time
  1543.  
  1544. ;    THESE ARE AN ORDERED SET - DO NOT RE-ARRANGE THEM
  1545.  
  1546. FSIZE    DB    '  ',0,0,0,0,0,0,0,0,'   '
  1547. IF DTYPE
  1548.   ADATE DB    'DD-Mmm-YY   '
  1549. ELSE
  1550.   ADATE DB    'MM-DD-YY   '
  1551. ENDIF
  1552. ATIME    DB    '00:00:00 '
  1553. ATTS    DB    ' R-O SYS ARC HDN VOL DIR',CR,LF,'$'
  1554. ATT_TXT    DB    ' R-O HDN SYS VOL DIR ARC'
  1555.  
  1556. ;    THESE ARE AN ORDERED SET - DO NOT RE-ARRANGE THEM
  1557.  
  1558. SMSG3    DB    CR,LF,'    Total of '
  1559. TOTS    DB    8 DUP (0),' bytes in '
  1560. TOTF    DB    8 DUP (0),' file'
  1561. TOTFS    DB    's',CR,LF,'$'
  1562.  
  1563. TOTFILE DW    0,0
  1564. TOTSIZE DW    0,0
  1565.  
  1566. SMSG4    DB    CR,LF,'      Total of  '
  1567. SIZLEFT    DB    '         bytes free',CR,LF,'$'
  1568.  
  1569. FREESIZ    DW    0,0
  1570.  
  1571. ;  Error messages
  1572.  
  1573. ERMSG1    DB    CR,LF,LF,7,'*** SORRY - REQUIRES DOS 2.0 OR HIGHER ***'
  1574.     DB    CR,LF,LF,'$'
  1575.  
  1576. ERMSG2    DB    CR,LF,7,'*** INVALID ARGUMENTS ***',CR,LF,'$'
  1577.  
  1578. ERMSG8    DB    CR,LF,7,'*** INVALID DRIVE *** ',CR,LF,'$'
  1579.  
  1580. ERMSG9    DB    CR,LF,7,'*** INVALID DIRECTORY *** ',CR,LF,'$'
  1581.  
  1582. ERRFLG    DB    0        ; 0 = Normal completion
  1583.  
  1584.  
  1585. ;  Miscellanious variables
  1586.  
  1587. TEN    DW    10        ; Divisor for conversion to decimal
  1588. FUNC    DB    FIRST        ; DOS functions - Find FIRST or NEXT file
  1589. HASDOT    DB    0        ; 1 if '.' is in argument list
  1590. DIRFLG    DB    0        ; Directory/subdirectory flag
  1591. SYSDATE DB    0,0,0,0,0,0,0
  1592. FILDATE DB    0,0,0,0,0,0,0
  1593. COMDAYS DW    0        ; Days (since 1-Jan-1980) to compare against
  1594. SYSDAYS DW    0        ; System days since 1-Jan-1980
  1595. FILDAYS DW    0        ; File     days since 1-Jan-1980
  1596. NDAYS    DB    '    '
  1597. HDAYS    DW    0
  1598. TEMP    DB    0,0,0,0
  1599.  
  1600. ;  Disk Transfer Buffers & Related Items
  1601.  
  1602. FSPEC    DB    30 DUP (' ')    ; DTA for FIND FIRST/NEXT function
  1603. FILENAM DB    12 DUP (' ')    ; File name from DOS-2 FIND FIRST/NEXT function
  1604.     DB    0,'$'
  1605.  
  1606. FULLNAM DB    ' :\',65 DUP (0),5 DUP (0)
  1607.  
  1608. DOT    DB    '.   $'        ; Dot directory name
  1609. DOTDOT    DB    '..  $'        ; Two dot directory name
  1610. DIRNAME    DB    ' <DIR>$'
  1611.     CSEG    ENDS
  1612.     END    NEW
  1613.